package base;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * SimpleDateFormat 线程不安全测试
 * 测试内容，取当前时间然后 format、parse后，在比较值会不一样
 */
public class SimpleDateFormatTest {

    private static final ThreadLocal<SimpleDateFormat> THREAD_LOCAL = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    public static void main(String[] args) {

        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5,
                100,
                1,
                TimeUnit.MINUTES,
                new LinkedBlockingQueue<>(),
                new UserFactory());

//        ExecutorService poolExecutor = Executors.newFixedThreadPool(5);

        Date d1 = new Date(15456464545888882L);
        Date d2 = new Date(15453756545888882L);
        Date d3 = new Date(154566547785488882L);
        Date d4 = new Date(15456464536798882L);
        Date d5 = new Date(15458048345367982L);
        Date d6 = new Date(15458345656367982L);

        ArrayList<Date> dates = Lists.newArrayList(d1, d2, d3, d4, d5, d6);

//        extracted1(dates,poolExecutor); // 线程不安全的

        extracted2(dates,poolExecutor); //


    }

    private static void extracted1(List<Date> dates, ThreadPoolExecutor poolExecutor) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Date date : dates) {
            poolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    String dateString = simpleDateFormat.format(date);
                    try {
                        Date parseDate = simpleDateFormat.parse(dateString);
                        String dateString2 = simpleDateFormat.format(parseDate);
                        System.out.println("当前线程：" + Thread.currentThread().getName() + " " + dateString.equals(dateString2));
                    } catch (ParseException e) {
                        System.out.println(dateString);
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    private static void extracted2(List<Date> dates,ThreadPoolExecutor poolExecutor) {
        for (Date date : dates) {
            poolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    SimpleDateFormat simpleDateFormat = THREAD_LOCAL.get();
                    if (simpleDateFormat == null) {
                        simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    }
                    String dateString = simpleDateFormat.format(date);
                    try {
                        Date parseDate = simpleDateFormat.parse(dateString);
                        String dateString2 = simpleDateFormat.format(parseDate);
                        System.out.println("当前线程：" + Thread.currentThread().getName() + " " + dateString.equals(dateString2));
                    } catch (ParseException e) {
                        System.out.println(dateString);
                        e.printStackTrace();
                    }
                }
            });
        }
    }

}

class UserFactory implements ThreadFactory {
    /**
     * 线程池编号，与线程组
     */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    /**
     * 线程编号，与线程名称前缀
     */
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    /**
     * 无参数构造方法
     */
    public UserFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        namePrefix = "myPool-" + poolNumber.getAndIncrement() + "-MyThread-";
    }

    @Override
    public Thread newThread(Runnable r) {
        // 实例化线程对象
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                0);
        return t;
    }
}